Skip to content

feat: enhanced target create with onboarding simplification flags#9780

Open
atharvau wants to merge 29 commits intoAzure:mainfrom
manaswita-chichili:audapure/cli-simplification-target-create
Open

feat: enhanced target create with onboarding simplification flags#9780
atharvau wants to merge 29 commits intoAzure:mainfrom
manaswita-chichili:audapure/cli-simplification-target-create

Conversation

@atharvau
Copy link
Copy Markdown
Member

Add --init-extended-location, --init-context, --init-hierarchy, --service-group, and --release-train flags to 'az workload-orchestration target create' to reduce onboarding from 15+ manual steps to a single command.

New commands:

  • target prepare: Prepares Arc cluster (cert-mgr, trust-mgr, extension, CL)
  • hierarchy create: Creates site hierarchy (SG, Site, Config, SiteRef)

Pre-operation hooks in target create:

  1. --init-extended-location: calls target_prepare to set up cluster + CL
  2. --init-context: discovers/creates WO context with capability injection
  3. --init-hierarchy: creates site hierarchy linked to context
  4. Default target-specification: injects Helm v3 in-cluster if not provided

Post-operation hook:
5. --service-group: links target to a service group after creation

8 flag combinations supported (from vanilla to full onboarding). Includes unit tests for hierarchy, SG link, utils, and target prepare.


This checklist is used to make sure that common guidelines for a pull request are followed.

Related command

General Guidelines

  • Have you run azdev style <YOUR_EXT> locally? (pip install azdev required)
  • Have you run python scripts/ci/test_index.py -q locally? (pip install wheel==0.30.0 required)
  • My extension version conforms to the Extension version schema

For new extensions:

About Extension Publish

There is a pipeline to automatically build, upload and publish extension wheels.
Once your pull request is merged into main branch, a new pull request will be created to update src/index.json automatically.
You only need to update the version information in file setup.py and historical information in file HISTORY.rst in your PR but do not modify src/index.json.

Copilot AI review requested due to automatic review settings April 14, 2026 05:25
@azure-client-tools-bot-prd
Copy link
Copy Markdown

Validation for Breaking Change Starting...

Thanks for your contribution!

@azure-client-tools-bot-prd
Copy link
Copy Markdown

Hi @atharvau,
Please write the description of changes which can be perceived by customers into HISTORY.rst.
If you want to release a new extension version, please update the version in setup.py as well.

@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented Apr 14, 2026

Thank you for your contribution! We will review the pull request and get back to you soon.

@github-actions
Copy link
Copy Markdown
Contributor

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

@github-actions
Copy link
Copy Markdown
Contributor

CodeGen Tools Feedback Collection

Thank you for using our CodeGen tool. We value your feedback, and we would like to know how we can improve our product. Please take a few minutes to fill our codegen survey

@github-actions
Copy link
Copy Markdown
Contributor

Hi @atharvau

Release Suggestions

Module: workload-orchestration

  • Please log updates into to src/workload-orchestration/HISTORY.rst
  • Update VERSION to 5.2.0 in src/workload-orchestration/setup.py

Notes

Add --init-extended-location, --init-context, --init-hierarchy, --service-group,
and --release-train flags to 'az workload-orchestration target create' to reduce
onboarding from 15+ manual steps to a single command.

New commands:
- target prepare: Prepares Arc cluster (cert-mgr, trust-mgr, extension, CL)
- hierarchy create: Creates site hierarchy (SG, Site, Config, SiteRef)

Pre-operation hooks in target create:
1. --init-extended-location: calls target_prepare to set up cluster + CL
2. --init-context: discovers/creates WO context with capability injection
3. --init-hierarchy: creates site hierarchy linked to context
4. Default target-specification: injects Helm v3 in-cluster if not provided

Post-operation hook:
5. --service-group: links target to a service group after creation

8 flag combinations supported (from vanilla to full onboarding).
Includes unit tests for hierarchy, SG link, utils, and target prepare.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@atharvau atharvau force-pushed the audapure/cli-simplification-target-create branch from 678e54f to 139d152 Compare April 14, 2026 05:33
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds onboarding-simplification flows to the workload-orchestration extension by introducing new helper commands (target prepare, hierarchy create) and new pre/post hooks on az workload-orchestration target create to reduce manual setup steps.

Changes:

  • Added onboarding module with utilities, constants, target_prepare, hierarchy_create, and service-group linking helper.
  • Extended workload-orchestration target create with --init-* and --service-group hooks plus a default target-specification when omitted.
  • Added unit tests covering target prepare behaviors, hierarchy creation flow/validation, SG link helper, and shared utils/consts.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/workload-orchestration/azext_workload_orchestration/tests/test_onboarding/test_target_prepare.py Unit tests for target prepare preflight/helm/extension/storage-class behaviors.
src/workload-orchestration/azext_workload_orchestration/tests/test_onboarding/test_sg_link_and_utils.py Unit tests for SG link helper plus utils/consts sanity checks.
src/workload-orchestration/azext_workload_orchestration/tests/test_onboarding/test_hierarchy_create.py Unit tests for hierarchy create validation and main flow variants.
src/workload-orchestration/azext_workload_orchestration/tests/test_onboarding/init.py Package marker/docstring for onboarding unit tests.
src/workload-orchestration/azext_workload_orchestration/onboarding/utils.py Shared REST/LRO helpers, in-process CLI invocation, and progress output utilities.
src/workload-orchestration/azext_workload_orchestration/onboarding/target_sg_link.py Helper to link a target to a Service Group and refresh target hierarchy via PUT.
src/workload-orchestration/azext_workload_orchestration/onboarding/target_prepare.py New target prepare command to set up cert-manager/trust-manager/extension/custom location.
src/workload-orchestration/azext_workload_orchestration/onboarding/hierarchy_create.py New hierarchy create command to create SG/Site/Configuration/References (optionally context/site ref).
src/workload-orchestration/azext_workload_orchestration/onboarding/consts.py Centralized API versions/defaults/constants for onboarding flows.
src/workload-orchestration/azext_workload_orchestration/onboarding/init.py Exposes onboarding entrypoints (target_prepare, hierarchy_create).
src/workload-orchestration/azext_workload_orchestration/custom.py Imports onboarding commands so command table can resolve them.
src/workload-orchestration/azext_workload_orchestration/commands.py Registers new command groups/commands for onboarding flows.
src/workload-orchestration/azext_workload_orchestration/aaz/latest/workload_orchestration/target/_create.py Adds onboarding flags + init hooks + default target-spec injection + SG link post-hook.
src/workload-orchestration/azext_workload_orchestration/_params.py Defines args for target prepare and hierarchy create.
src/workload-orchestration/azext_workload_orchestration/_help.py Adds help content for the new onboarding commands.

Comment on lines +576 to +580
logger.warning("Failed to update context capabilities: %s", exc)

def _handle_init_hierarchy(self):
"""Auto-create a regular site hierarchy (RG-scoped, no SG)."""
from azure.cli.core import get_default_cli
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resp.text() is called as a function, but requests.Response.text is a string property. This will raise TypeError when the non-200/201 branch is hit, hiding the real REST error. Use resp.text (or resp.content) in the log message instead.

Copilot uses AI. Check for mistakes.
"""Unit tests for target prepare command."""

import unittest
from unittest.mock import patch, MagicMock, PropertyMock
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports: PropertyMock is imported but not used in this test module. Removing unused imports keeps the test code easier to maintain.

Suggested change
from unittest.mock import patch, MagicMock, PropertyMock
from unittest.mock import patch, MagicMock

Copilot uses AI. Check for mistakes.
Comment on lines +614 to +631
try:
return cli.invoke(args)
finally:
sys.stdout, sys.stderr = old_stdout, old_stderr

# Step 1: Create site
_invoke_silent([
"rest", "--method", "put", "--url", site_url,
"--body", site_body,
"--resource", "https://management.azure.com",
"--header", "Content-Type=application/json",
"-o", "none",
])

# Step 2: Create configuration
config_url = (
f"https://{location}.management.azure.com"
f"/subscriptions/{sub_id}/resourceGroups/{rg}"
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_handle_init_hierarchy suppresses stdout/stderr but never checks the cli.invoke(...) return codes. As written, site/config/reference creation failures will still print a final "created [OK]" message and the target create will continue with a partially-initialized hierarchy. Capture the exit code(s) (or use invoke_cli_command) and raise CLIInternalError on non-zero to avoid silent failures.

Copilot uses AI. Check for mistakes.
Comment on lines +135 to +140
_args_schema.init_hierarchy = AAZStrArg(
options=["--init-hierarchy"],
arg_group="Onboarding",
help="Auto-create a regular site hierarchy. Value is the site name. "
"Creates a Site in the target's resource group and links to context.",
)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says --init-hierarchy creates a full hierarchy including Service Group, but the flag help here (and implementation in _handle_init_hierarchy) describes an RG-scoped Site/Configuration flow without Service Group creation. Please align the PR description and/or the flag behavior/help so users have an accurate expectation of what gets created.

Copilot uses AI. Check for mistakes.
options=["--release-train"],
arg_group="Onboarding",
help="Release train for WO extension (used with --init-extended-location). "
"Default: 'dev'. Options: dev, preview, stable.",
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --release-train help says the default is 'dev', but target_prepare() defaults release_train to DEFAULT_RELEASE_TRAIN which is currently 'stable'. Please update this help text (or the underlying default) so the CLI guidance matches actual behavior.

Suggested change
"Default: 'dev'. Options: dev, preview, stable.",
"Default: 'stable'. Options: dev, preview, stable.",

Copilot uses AI. Check for mistakes.
c.argument(
'release_train',
options_list=['--release-train'],
help='Extension release train. Defaults to preview.',
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--release-train help says "Defaults to preview", but target_prepare() sets release_train = release_train or DEFAULT_RELEASE_TRAIN and DEFAULT_RELEASE_TRAIN is currently stable. Please align the parameter help text (or the constant default) to avoid misleading users.

Suggested change
help='Extension release train. Defaults to preview.',
help='Extension release train. Defaults to stable.',

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +95
if target_data and isinstance(target_data, dict):
# Strip read-only fields
body = {
"location": target_data.get("location", ""),
"properties": target_data.get("properties", {}),
}
if "extendedLocation" in target_data:
body["extendedLocation"] = target_data["extendedLocation"]

Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hierarchy refresh PUT body only includes location, properties, and optionally extendedLocation. For ARM resources, omitting fields like tags can clear them, and sending back properties from GET may include read-only fields that can cause the PUT to fail. Consider preserving tags/other writable top-level fields and stripping read-only fields (or using PATCH if supported) so the refresh doesn't accidentally drop metadata or fail unnecessarily.

Copilot uses AI. Check for mistakes.
"""Hierarchy create command - creates a hierarchy level in a single command.

Wraps 4-6 operations into one:
0. Auto-create Context + update hierarchies/capabilities (if needed)
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module docstring states the command will "update hierarchies/capabilities" in the context, but the implementation (_update_context_if_needed) only logs that an update may be needed and does not perform any update. Please either implement the update (e.g., via the existing workload-orchestration context update command) or adjust this description so it matches actual behavior.

Suggested change
0. Auto-create Context + update hierarchies/capabilities (if needed)
0. Auto-create Context (if needed)

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +10
import json
import unittest
from unittest.mock import patch, MagicMock, call
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports: json and call are imported but not used in this test module. Removing them avoids confusion about expected usage.

Suggested change
import json
import unittest
from unittest.mock import patch, MagicMock, call
import unittest
from unittest.mock import patch, MagicMock

Copilot uses AI. Check for mistakes.
Atharva and others added 13 commits April 14, 2026 11:13
- Extract _handle_init_context (150 lines) → context_init.py
- Extract _handle_init_hierarchy (100 lines) → hierarchy_init.py
- Add parse_arm_id() to utils.py (replaces 6 inline ARM ID parsers)
- Add invoke_silent() to utils.py (replaces 4 stdout suppression blocks)
- Use DEFAULT_TARGET_SPECIFICATION from consts.py
- _create.py custom code: 400 lines → 60 lines (orchestration only)
- Each onboarding module now has a single clear responsibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move context_id config resolution before --init-hierarchy (hierarchy
  needs context_id for site-reference linking)
- Extract _resolve_context_id_from_config() for clarity
- Fix hierarchy_init.py sub_id: parse from context_id ARM ID or fall
  back to CLI Profile instead of cli_ctx.data (which returns None)

Tested: all 7 flag combinations pass on live AKS cluster

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The cluster preparation logic is now only accessible via
'target create --init-extended-location'. The underlying target_prepare
module is retained as an internal dependency.

Removed from: commands.py, _params.py, _help.py, custom.py

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hierarchy creation is now only accessible via 'target create --init-hierarchy'.
The underlying modules are retained as internal dependencies.

Removed from: commands.py, _params.py, _help.py, custom.py

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix --release-train help text: 'dev' -> 'stable' to match DEFAULT_RELEASE_TRAIN
- Remove unused imports: PropertyMock from test_target_prepare, json/call from test_sg_link_and_utils
- Fix hierarchy_create.py docstring: remove claim about updating capabilities
- Preserve tags in target_sg_link refresh PUT to avoid dropping metadata

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t flags from target create

- Remove --init-extended-location, --init-context, --init-hierarchy, --release-train from target create
- Add 'target init' as standalone command (wraps target_prepare)
- Keep --service-group and default target-spec on target create
- Aligns with team decision: cluster setup and hierarchy as separate commands

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implements 'az workload-orchestration target deploy' that chains
review, publish, and install into a single command with LRO polling.

- Supports --skip-review and --skip-install flags
- Supports --config-file for pre-review configuration
- Uses send_raw_request with ARM resource auth
- Polls LRO via Location/Azure-AsyncOperation headers

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add --solution-template-name + --solution-template-version (friendly name)
  as alternative to --solution-template-version-id (ARM ID)
- Add --solution-template-rg for cross-RG templates
- Add --resume-from publish|install with --solution-version-id
- Add --solution-dependencies pass-through to review
- Add --config for pre-review configuration set
- Proper mutual exclusivity validation between ARM ID and friendly name
- Dynamic step counter adjusts based on active steps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The review LRO response nests the solution version ARM ID at
properties.id, not properties.properties.id or the top-level id.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Config set needs --solution flag to use solution templates (not config templates)
- Improved solutionVersionId extraction debug logging

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove --skip-review, --skip-install, --no-wait from target deploy
- Fix disallowed HTML tags in help (wrap placeholders in backticks)
- Add short aliases: --stv-id, --stv, --ct-version for long options
- Remove --no-wait example from help

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove 'Next steps' and 'Extended Location JSON' print lines
- Keep diagnostic summary and success message
- CLI framework already prints the return dict as JSON

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Counter now increments only on step start, not on status update.
Shows [1/3]...[1/3] OK, [2/3]...[2/3] OK, [3/3]...[3/3] OK.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Keep it only on error paths for debugging.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

When --site-id is provided, automatically creates a site-reference
linking the site to the context after creation. Site reference name
is derived from the site name (e.g., mySite -> mySite-ref).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

…deploy

Users can use individual commands (target review/publish/install) for
partial operations. Deploy is now always a full chain.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

logger.warning("Site reference creation failed: %s", exc)
raise CLIError(
f"Context created successfully, but site reference creation failed: {exc}\n"
f"Run manually:\n"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this

tags.Element = AAZStrArg()

# Custom arg: --site-id (not sent to ARM, used in post_operations)
_args_schema.site_id = AAZStrArg(
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this optionalk should itg be optional if passewd create site reference

target install now supports two flows:
1. Full deploy: --solution-template-name + --stv (or --stv-id)
   Runs: config-set (opt) → review → publish → install
2. Direct install: --solution-version-id (old flow)
   Runs: install only

Removed: target deploy command, _params, _help, commands.py registration.
Kept: target_deploy.py module (used internally by install pre_operations).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

…late

Config-set now auto-derives template info from solution template args:
  config-template-rg → solution-template-rg or --resource-group
  config-template-name → solution-template-name
  config-template-version → solution-template-version

Usage simplified to:
  az wo target install -g rg -n target --solution-template-name X --stv 1.0.0 --configuration values.yaml

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Better reflects the command's purpose - it prepares the cluster,
not a specific target.

Command: az workload-orchestration cluster init -c cluster -g rg -l region

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Per Shubham's feedback: don't touch --target-specification.
Upcoming non-K8s workloads may change this, marked as future work.
Users must provide --target-specification explicitly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Solution templates can be in any RG, so friendly name resolution
uses the target's --resource-group. For cross-RG templates, use
the full ARM ID via --solution-template-version-id.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Removed --stv-id and --stv aliases. Use full names:
  --solution-template-version-id
  --solution-template-version

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Removed:
- --skip-cert-manager, --skip-trust-manager
- --kube-config, --kube-context
- Failed extension auto-reinstall logic

Kept args: -c, -g, -l, --release-train, --extension-version,
--extension-name, --custom-location-name

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

@yonzhan yonzhan requested a review from necusjz April 16, 2026 04:43
Creates full resource stack in one command:
  1. Site (with level label)
  2. Configuration (in specified region)
  3. ConfigurationReference (links site to config)

Supports:
  - ResourceGroup: single site via --resource-group + shorthand/YAML
  - ServiceGroup: nested hierarchy up to 3 levels via YAML file

Usage:
  az wo hierarchy create -g rg --configuration-location eastus2euap --hierarchy-spec 'name=X level=factory'
  az wo hierarchy create --configuration-location eastus2euap --hierarchy-spec hierarchy.yaml

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

…onfigs

- ResourceGroup flow: Site + Config + ConfigRef (3 resources)
- ServiceGroup flow: recursive SG + Site + Config + ConfigRef (up to 3 levels, 12 resources)
- Configs are always RG-scoped (--resource-group required)
- RBAC propagation wait after each SG creation (polls site list)
- Removed old hierarchy_create.py, using clean v2

E2E tested: 3-level SG hierarchy created successfully.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines:
2 pipeline(s) require an authorized user to comment /azp run to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants